<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>websocket编程</title>
</head>
<body>
<script>
    class WSClient {
        // 构造函数，接收 WebSocket 服务器地址作为参数
        constructor(url) {
            this.url = url; // 服务器地址
            this.reconnectInterval = 3000; // 重连间隔时间（毫秒）
            this.maxReconnectAttempts = 5; // 最大重试次数
            this.reconnectAttempts = 0; // 当前重试次数计数器
            this.connect(); // 初始化连接
        }

        connect()  {
            // 创建 WebSocket 实例
            this.ws = new WebSocket(this.url);

            // 连接成功时触发
            this.ws.onopen = () => {
                this.reconnectAttempts = 0; // 重置重试次数
                this.startHeartbeat(); // 启动心跳机制
                // 更新页面上的响应区域文本
                var rt = document.getElementById("responseText");
                rt.value = "连接开启了";
            };

            // 接收到服务器消息时触发
            this.ws.onmessage = (event) => {
                if(event.data === 'HEARTBEAT_ACK') {
                    // 如果是心跳响应，重置心跳计时器
                    this.resetHeartbeat();
                } else {
                    // 否则将收到的消息显示在文本框中
                    var rt = document.getElementById("responseText");
                    rt.value = rt.value + "\n" + event.data;
                }
            };

            // 连接关闭时触发
            this.ws.onclose = () => {
                var rt = document.getElementById("responseText");
                rt.value = rt.value + "\n" + "连接关闭";
                // 如果重试次数未达上限，尝试重新连接
                if(this.reconnectAttempts < this.maxReconnectAttempts) {
                    setTimeout(() => this.reconnect(), this.reconnectInterval);
                    this.reconnectAttempts++;
                }
            };
        }

        reconnect() {
            console.log(`重新连接...尝试次数 ${this.reconnectAttempts}`);
            this.connect(); // 调用 connect 方法重新建立连接
        }

        startHeartbeat() {
            // 每隔 5 秒向服务器发送一次心跳消息
            this.heartbeatTimer = setInterval(() => {
                this.ws.send('HEARTBEAT');
            }, 5000);
        }

        resetHeartbeat() {
            clearInterval(this.heartbeatTimer); // 清除当前心跳定时器
            this.startHeartbeat(); // 重新启动心跳
        }

        send(message) {
            // 如果连接已打开，则发送消息
            if (this.ws.readyState == WebSocket.OPEN) {
                this.ws.send(message);
            } else {
                alert("连接没有开启...");
            }
        }
    }

    // 检查浏览器是否支持 WebSocket
    if (window.WebSocket) {
        // 创建客户端实例，连接地址为 ws://localhost:9999/ws
        client = new WSClient("ws://localhost:9999/ws");

        // 定义发送消息的函数
        function send(message) {
            client.send(message); // 调用客户端发送方法
            console.log("发送消息到服务器:", message) // 控制台打印日志
        }
    } else {
        alert("当前浏览器不支持！");
    }
</script>
<form onsubmit="return false">
    <!-- 输入框，用于输入要发送的消息 -->
    <textarea name="message" style="height: 600px;width:600px"></textarea>
    <!-- 发送按钮，点击后调用 send 函数 -->
    <input type="button" value="发送消息" onclick="send(this.form.message.value)">
    <!-- 显示服务器返回消息的文本区域 -->
    <textarea id="responseText" style="height: 600px;width: 600px"></textarea>
    <!-- 清空显示区域按钮 -->
    <input type="button" value="清空内容" onclick="document.getElementById('responseText').value=''">
</form>
</body>
</html>